/*********************************************************************************
Organization 					: 				Georgia Institute of Technology
  
Institute 						:				Cognitive Computing Group(CCL)
 
Authors							: 				Manish Mehta 
 												
Class							:				BuildingIdleFix
 
Function						: 				A class for holding fixes for situations 
												when building is idle 
****************************************************************************/

package behavioradaptation.fixes;


import java.util.List;
import java.util.Vector;

import cbr.episodicCBR.EpisodicCBR;

import planninglanguage.plans.BasicOperatorPlan;
import planninglanguage.plans.MultiPlan;
import planninglanguage.plans.Plan;
import planninglanguage.plans.SequentialPlan;
import planninglanguage.plans.TrainBOPlan;
import trace.Entry;
import trace.Trace;
import base.WargusStateImporter;
import base.WargusUnit;
import behavioradaptation.analysisdata.AbstractedTrace;
import behavioradaptation.analysisdata.FixData;
import behavioradaptation.analysisdata.IdleData;
import behavioradaptation.analysisdata.PlanFailuresData;
import behavioradaptation.analysisdata.ResourceData;
import behavioradaptation.reasoner.TraceHelpers;


public class BuildingIdleFix {
	static int BUILDING_IDLE_CYCLE = 200;

	public static void fix(List<PlanFailuresData> a_planFailuresList, AbstractedTrace a_abstractedtrace, 
			FixData a_fxdata, EpisodicCBR a_cbr) throws Exception
	{
		Vector <IdleData> a_idleDataList = a_abstractedtrace.getIdleData();
		Trace a_trace = a_abstractedtrace.getTrace();
		Vector<ResourceData> a_resourceData = a_abstractedtrace.getSelfResourceData();
		for(int i = 0; i < a_idleDataList.size(); i++)
		{
			IdleData id = (IdleData)a_idleDataList.get(i);
			int index = id.getStartIndex();
			boolean index_found = false;
			int foundindex = 0;
			int gold = 0;
			int wood = 0;
			Plan nplan, rbplan = null;
			for(int j = index; j <id.getEndIndex(); j++)
			{
				ResourceData a_resd = (ResourceData)a_resourceData.get(index);			
				if(a_resd.gold > 800 && a_resd.wood > 500)
				{
					gold = a_resd.gold;
					wood = a_resd.wood;
					index_found = true;
					foundindex = j;
				}						
			}	
			Entry e = (Entry)a_trace.get(foundindex);
			// Right now we are just modifying the Basic Operator Plan 
			// so find the basic entry plan if the current entry is not the 
			// one that is a basic entry plan 
			while (!(e.getPlan() instanceof BasicOperatorPlan))
			{
				if(foundindex > 0)
					e = (Entry)a_trace.get(foundindex--);
				else return;
			}
			// Right now the building Idle is only checked for human-barracks 
			// has to be extended for other building types
			// Right now the BUILDING_IDLE_CYCLE is 200
			if(id.getUnit().getType()==WargusStateImporter.unitTypeToInteger("human-barracks") && 
			   ((id.getEndCycle() - id.getStartCycle()) > BUILDING_IDLE_CYCLE) && index_found)			
			{
					e = (Entry)a_trace.get(foundindex);
					// If the building was idle check whether there were enough 
					// resources available at that moment to train a footman
					rbplan = getUnitstobeTrained(id.getUnit(), gold, wood, "footman");
					// Modify the Case Base with the modified plan 
					TraceHelpers.modifyCaseBase(e.getPlan(), a_trace, rbplan,e, false, a_cbr);
			}		
		}	
	}
	/*
	 * Get the amount of units that can be trained at that moment with the available resources
	 */ 
	public static Plan getUnitstobeTrained(WargusUnit unit , int gold, int wood, String UnitType) throws Exception
	{
		Plan rbplan = null;
		int number = 1;
		int goldcost = WargusStateImporter.unitCostGold(UnitType);
		int woodcost = WargusStateImporter.unitCostWood(UnitType);
		do 
		{
			if((gold < (number*goldcost)) || (wood < (number*woodcost)))
				break;
			else
				number++;
		}while(true);
		MultiPlan seqp = new SequentialPlan();
		for( int i = 0; i < number; i++)
		{	
			rbplan = new TrainBOPlan(unit.getUnitID(), WargusStateImporter.unitTypeToInteger(UnitType), null, null, null);
			seqp.add(rbplan);
		}
		return seqp;
	}
	
}
